home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvitops
/
pk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-25
|
12KB
|
524 lines
static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/pk.c,v 1.7 90/10/19 09:54:55 jjc Exp $";
#include "dvitops.h"
#define pk_id 89
#if 0
enum pk_command { pk_xxx1 = 240, pk_xxx2 = 241, pk_xxx3 = 242, pk_xxx4 = 243,
pk_yyy = 244, pk_post = 245, pk_no_op = 246, pk_pre = 247 };
#else
#define pk_xxx1 240
#define pk_xxx2 241
#define pk_xxx3 242
#define pk_xxx4 243
#define pk_yyy 244
#define pk_post 245
#define pk_no_op 246
#define pk_pre 247
#endif
static struct {
integer llx, lly, urx, ury;
} bb; /* bounding box for the entire font */
#ifdef PROTO
static void out_byte(PROMOTED_UNSIGNED_CHAR c, FILE *psfp);
static void blacken(integer start, integer n, unsigned char *buf);
static integer packed_num(int dyn_f);
static void bitmap_char(integer h, integer w, FILE *psfp);
static integer makeinteger(unsigned char *p);
static int generate_char(PROMOTED_UNSIGNED_CHAR flag, unsigned char *data,
size_t len, FILE *psfp);
#else
static void out_byte();
static void blacken();
static integer packed_num();
static void bitmap_char();
static integer makeinteger();
static int generate_char();
#endif
static struct pk_info {
integer ds;
integer hppp;
integer vppp;
unsigned char flag[MAXCHARS];
size_t len[MAXCHARS];
unsigned char *data[MAXCHARS];
} *pk_table[MAXFONTS];
static integer nbytes;
char *find_pk_file(name, mag)
char *name;
int mag;
{
FILE *pkfp;
int i;
static char buf[10*FILENAME_MAX];
char *ptr = buf;
static char sep[2] = {AREA_LIST_SEP, '\0'};
for (i = 0; texpk[i] != '\0'; i++)
if (texpk[i] == '%') {
switch(texpk[i+1]) {
case 'f': case 'F':
strcpy(ptr, name);
break;
case 'd': case 'D':
sprintf(ptr, "%d", mag);
break;
default:
sprintf(ptr, "%c", texpk[i+1]);
}
++i;
ptr += strlen(ptr);
}
else
*ptr++ = texpk[i];
*ptr = '\0';
for (ptr = strtok(buf, sep); ptr != NULL; ptr = strtok((char *)NULL, sep)) {
if ((pkfp = FOPEN_RB(ptr)) != NULL) {
fclose(pkfp);
return ptr;
}
}
return NULL;
}
int load_pk_font(f, name, used, at_size, checksum, width, rounded_width)
int f;
char *name, *used;
integer at_size, checksum, *width, *rounded_width;
{
FILE *pkfp;
integer n;
integer cs;
double sppp;
int i;
if ((pkfp = FOPEN_RB(name)) == NULL) {
message(ERROR,
"can't find pk file for %s: using white space instead", name);
return 0;
}
#ifdef HAVE_SETVBUF
setvbuf(pkfp, (char *)NULL, _IOFBF, 8192);
#endif
if ((pk_table[f] = (struct pk_info *)
calloc(1, sizeof(struct pk_info))) == NULL)
out_of_memory();
if (uread1(pkfp) != pk_pre)
goto bad;
if (uread1(pkfp) != pk_id)
goto bad;
n = uread1(pkfp);
fseek(pkfp, n, 1);
pk_table[f]->ds = sread4(pkfp);
cs = sread4(pkfp);
pk_table[f]->hppp = sread4(pkfp);
pk_table[f]->vppp = sread4(pkfp);
/* sppp = scaled points per pixel
sppp*dx = width in scaled points */
sppp = (double)at_size*1048576.0*65536.0
/((double)pk_table[f]->ds*(double)pk_table[f]->hppp);
if (cs != checksum)
message(WARNING, "%s: checksums don't match\n", name);
for (;;) {
unsigned char command = uread1(pkfp);
if (feof(pkfp) || ferror(pkfp))
goto bad;
if (((unsigned)command >> 4) == 15) {
switch (command) {
case pk_xxx1 :
n = uread1(pkfp); break;
case pk_xxx2 :
n = uread2(pkfp); break;
case pk_xxx3 :
n = uread3(pkfp); break;
case pk_xxx4 :
n = sread4(pkfp); break;
case pk_yyy :
(void) sread4(pkfp); break;
case pk_post :
for (i = 0; i < MAXCHARS; i++)
if (used[i] && width[i] == (integer) LONG_MAX)
goto bad;
fclose(pkfp);
return 1;
case pk_no_op :
break;
default:
goto bad;
}
if (pk_xxx1 <= command && command <= pk_xxx4)
fseek(pkfp, n, 1);
}
else {
integer cc, pl;
integer tfm;
double dx;
unsigned char c;
size_t len;
unsigned char flag = command;
command &= 0x07;
if (command == 0x07) {
pl = sread4(pkfp);
cc = sread4(pkfp);
tfm = sread4(pkfp);
dx = (double)sread4(pkfp)/65536.0;
fseek(pkfp, -4L, 1);
pl -= 4;
}
else if (command & 0x04) {
pl = uread2(pkfp);
pl |= (integer)(command & 0x03) << 16;
cc = uread1(pkfp);
tfm = uread3(pkfp);
dx = (double)uread2(pkfp);
fseek(pkfp, -2L, 1);
pl -= 3;
}
else {
pl = uread1(pkfp);
pl |= (command & 0x03) << 8;
cc = uread1(pkfp);
tfm = uread3(pkfp);
dx = (double)uread1(pkfp);
fseek(pkfp, -1L, 1);
pl -= 3;
}
if (cc < 0 || cc >= MAXCHARS) {
fseek(pkfp, pl, SEEK_CUR);
continue;
}
c = (unsigned char)cc;
if (!used[c]) {
pk_table[f]->data[c] = NULL;
fseek(pkfp, pl, SEEK_CUR);
}
else {
if (pl < 0 || pl > SIZE_MAX)
goto bad;
len = (size_t)pl;
width[c] = scale(tfm, at_size);
rounded_width[c] = (integer)(dx*sppp);
pk_table[f]->flag[c] = flag;
pk_table[f]->len[c] = len;
if ((pk_table[f]->data[c] = (unsigned char *)malloc(len))
== NULL)
out_of_memory();
if (fread((char *)pk_table[f]->data[c], 1, len, pkfp) != len)
goto bad;
}
}
}
/* can't get here */
bad:
message(ERROR, "%s: bad pk file: using white space instead", name);
return 0;
}
static unsigned char *ptr;
static char biti;
static integer rc;
#define get_nyb() (biti == 0 ? (biti=4, (unsigned)*ptr>>4) \
: (biti = 0, *ptr++ & 0x0f))
static integer packed_num(dyn_f)
int dyn_f;
{
integer i, j;
integer n;
i = get_nyb();
if (i == 0) {
do {
j = get_nyb();
i++;
} while (j == 0);
while (i > 0) {
j = (j << 4) + get_nyb();
i--;
}
n = (j - 15 + ((13 - dyn_f) << 4) + dyn_f);
}
else if (i <= dyn_f)
n = i;
else if (i < 14)
n = ((i - dyn_f - 1) << 4) + get_nyb() + dyn_f + 1;
else {
rc = i == 14 ? packed_num(dyn_f) : 1;
n = packed_num(dyn_f);
}
return n;
}
/* this can be made a lot more efficient later */
static void blacken(start, n, buf)
integer start, n;
unsigned char *buf;
{
integer i;
for (i = start; i < start + n; i++)
buf[(size_t)(i/8)] |= (unsigned)128 >> (int)(i & 7);
}
static char *hex = "0123456789ABCDEF";
static void out_byte(c, psfp)
unsigned char c;
FILE *psfp;
{
static int cols = 0;
putc(hex[(unsigned)(c) >> 4],psfp);
putc(hex[(c) & 15],psfp);
if ((cols += 2) > 70) {
cols = 0;
putc('\n', psfp);
}
++nbytes;
}
/* postscript requires that the bitmap of each row be padded out to an
integral number of bytes, so unfortunately we can't just copy the bitmap
in the pk file; this function could probably be made faster, but most
of the characters that pk format represents by bitmaps are fairly small */
static void bitmap_char(h, w, psfp)
integer h, w;
FILE *psfp;
{
integer i, j;
unsigned mask = 0x80;
unsigned char curbyte = 0;
unsigned curmask = 0x80;
for (i = 0; i < h; i++)
for (j = 0; j < w; j++) {
if (*ptr & mask)
curbyte |= curmask;
if ((mask >>= 1) == 0) {
mask = 0x80;
ptr++;
}
if ((curmask >>= 1) == 0 || j == w - 1) {
out_byte(curbyte, psfp);
curbyte = 0;
curmask = 0x80;
}
}
/* the value of ptr is checked on return to make sure we have used the right
number of bytes */
if (mask != 0x80)
ptr++;
}
static integer makeinteger(p)
unsigned char *p;
{
return (((integer)p[0]<<24) | ((integer)p[1]<<16) | (p[2]<<8) | p[3]);
}
/*
output strings have one of the following forms:
(4 byte integers are always signed)
flag[1] dm[1] w[1] h[1] hoff[+1] voff[+1] flag = 0
flag[1] dm[2] w[2] h[2] hoff[+2] voff[+2] flag = 1
flag[1] dx[4] dy[4] w[4] h[4] hoff[4] voff[4] flag = 2
*/
/* returns 0 on error != 0 otherwise */
static int generate_char(flag, data, len, psfp)
unsigned char flag;
unsigned char *data;
size_t len;
FILE *psfp;
{
int black = (flag & 0x08) != 0;
integer h, w;
int dyn_f;
integer hoff, voff;
integer curcol, currow;
unsigned char *rowbuf;
size_t buflen;
dyn_f = (unsigned)flag >> 4;
ptr = data;
rc = 0;
biti = 0;
fputc('<',psfp);
if ((flag & 0x07) == 0x07) {
int i;
out_byte(2, psfp);
for (i = 0; i < 24; i++)
out_byte(ptr[i], psfp);
ptr += 8;
w = makeinteger(ptr); ptr += 4;
h = makeinteger(ptr); ptr += 4;
hoff = makeinteger(ptr); ptr += 4;
voff = makeinteger(ptr); ptr += 4;
}
else if (flag & 0x04) {
int i;
out_byte(1, psfp);
for (i = 0; i < 10; i++)
out_byte(ptr[i], psfp);
ptr += 2;
w = (ptr[0] << 8) | ptr[1]; ptr += 2;
h = (ptr[0] << 8) | ptr[1]; ptr += 2;
hoff = *ptr++;
if (hoff >= 128)
hoff -= 256;
hoff <<= 8;
hoff |= *ptr++;
voff = *ptr++;
if (voff >= 128)
voff -= 256;
voff <<= 8;
voff |= *ptr++;
}
else {
int i;
out_byte(0, psfp);
for (i = 0; i < 5; i++)
out_byte(ptr[i], psfp);
ptr++;
w = *ptr++;
h = *ptr++;
hoff = *ptr++;
if (hoff >= 128)
hoff -= 256;
voff = *ptr++;
if (voff >= 128)
voff -= 256;
}
if (-hoff < bb.llx)
bb.llx = -hoff;
if (w-hoff > bb.urx)
bb.urx = w-hoff;
if (voff + 1 - h < bb.lly)
bb.lly = voff + 1 - h;
if (voff + 1 > bb.ury)
bb.ury = voff + 1;
if (dyn_f == 14) {
bitmap_char(h, w, psfp);
if (data + len != ptr)
return 0;
fputc('>',psfp);
return 1;
}
currow = curcol = 0;
buflen = (size_t)((w + 7) / 8);
if (buflen == SIZE_MAX) /* we'd get an infinite loop if we allowed this */
return 0;
rowbuf = (unsigned char *)calloc(1, buflen);
if (rowbuf == NULL)
out_of_memory();
while (currow < h) {
integer run = packed_num(dyn_f);
while (curcol + run >= w) {
size_t i;
integer j;
if (black)
blacken(curcol, w - curcol, rowbuf);
for (j = 0; j <= rc; j++) {
for (i = 0; i < buflen; i++)
out_byte(rowbuf[i],psfp);
}
for (i = 0; i < buflen; i++)
rowbuf[i] = 0;
currow++; currow += rc; rc = 0;
run -= w - curcol;
curcol = 0;
}
if (black)
blacken(curcol, run, rowbuf);
curcol += run;
black = !black;
}
if (biti > 0)
ptr++;
if (data + len != ptr)
return 0;
fputc('>',psfp);
free((char *)rowbuf);
return 1;
}
integer emit_pk_font(f, name, used, psfp)
int f;
char *name;
char *used;
FILE *psfp;
{
int i, nused;
nbytes = 0;
if (pk_table[f] == NULL)
cant_happen();
fprintf(psfp, "%%%%BeginFont: %s\n", name);
fprintf(psfp, "/%s %ld %ld %ld\n", name, (long)(pk_table[f]->ds),
(long)(pk_table[f]->hppp), (long)(pk_table[f]->vppp));
bb.llx = bb.lly = bb.urx = bb.ury = 0;
nused = 0;
fputs("EmptyEncoding 256 array copy\n", psfp);
for (i = 0; i < MAXCHARS; i++)
if (used[i]) {
fprintf(psfp, "dup %d /c%d put\n", i, i);
++nused;
}
/* allow room for /.notdef */
fprintf(psfp, "\n%d dict dup begin\n", nused+1);
for (i = 0; i < MAXCHARS; i++)
if (used[i]) {
if (pk_table[f]->data[i] == NULL)
cant_happen();
fprintf(psfp, "/c%d", i);
if (!generate_char(pk_table[f]->flag[i], pk_table[f]->data[i],
pk_table[f]->len[i], psfp))
message(FATAL_ERROR,
"char %d in the .pk file for %s is bad: use pktype",
i, name);
fputs("def\n", psfp);
}
fprintf(psfp, "end %ld %ld %ld %ld DefinePKFont\n", (long)(bb.llx),
(long)(bb.lly), (long)(bb.urx), (long)(bb.ury));
fputs("%%EndFont\n", psfp);
/* this is a fairly good estimate of the overhead for each font */
return nbytes + 1024 + 2000 + 20*(nused+1);
/* nbytes for the strings, 1024 for the encoding vector,
20 for each of the nused+1 entries in the dictionary
plus 2000 for general overhead */
}
void free_pk_font(n)
int n;
{
int i;
struct pk_info *p = pk_table[n];
if (pk_table[n] == NULL)
cant_happen();
for (i = 0; i < MAXCHARS; i++)
if (p->data[i] != NULL)
free((char *)(p->data[i]));
free((char *)p);
pk_table[n] = NULL;
}
/*
Local Variables:
c-indent-level: 4
c-continued-statement-offset: 4
c-brace-offset: -4
c-argdecl-indent: 0
c-label-offset: -4
tab-width: 4
End:
*/